<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>XML/JSON互转工具</title>
    <style>
        /* 基础样式重置 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        /* CSS变量定义 */
        :root {
            --primary-color: #3498db;
            --primary-hover: #2980b9;
            --secondary-color: #95a5a6;
            --secondary-hover: #7f8c8d;
            --background-color: #f4f4f4;
            --card-background: #ffffff;
            --text-color: #333333;
            --border-color: #dddddd;
            --border-radius: 5px;
            --box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            --font-family: Arial, sans-serif;
            --monospace-font: 'Courier New', monospace;
            --gap: 20px;
        }
        
        body {
            font-family: var(--font-family);
            background-color: var(--background-color);
            color: var(--text-color);
            margin: 0;
            padding: 20px;
        }
        
        .container {
            max-width: 95%;
            margin: 0 auto;
        }
        
        /* 头部样式 */
        header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 30px;
            padding-bottom: 15px;
            border-bottom: 1px solid #eee;
        }
        
        h1 {
            color: #2c3e50;
            font-size: 28px;
        }
        
        .back-btn {
            background-color: var(--primary-color);
            color: white;
            padding: 10px 20px;
            text-decoration: none;
            border-radius: var(--border-radius);
            transition: background-color 0.3s ease;
            font-size: 14px;
        }
        
        .back-btn:hover {
            background-color: var(--primary-hover);
        }
        
        /* 工具卡片样式 */
        .tool-card {
            background-color: var(--card-background);
            padding: 20px;
            border-radius: 8px;
            box-shadow: var(--box-shadow);
        }
        
        /* 按钮组样式 */
        .btn-group {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }
        
        .btn {
            background-color: var(--primary-color);
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: var(--border-radius);
            cursor: pointer;
            font-size: 14px;
            transition: background-color 0.3s ease;
        }
        
        .btn:hover {
            background-color: var(--primary-hover);
        }
        
        .btn:active {
            transform: translateY(1px);
        }
        
        .btn-secondary {
            background-color: var(--secondary-color);
        }
        
        .btn-secondary:hover {
            background-color: var(--secondary-hover);
        }
        
        /* 输入输出容器样式 */
        .io-container {
            display: flex;
            gap: 20px;
            align-items: flex-start;
        }
        
        /* 输入输出区域 */
        .io-panel {
            flex: 1;
            min-width: 0;
        }
        
        .io-header {
            font-weight: bold;
            margin-bottom: 10px;
            color: #555;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        /* 文本区域样式 */
        .textarea-wrapper {
            position: relative;
            height: 500px;
        }
        
        /* 行号容器样式 */
        .lined-area {
            position: relative;
            display: flex;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }
        
        /* 行号区域样式 */
        .line-numbers {
            background-color: #f0f0f0;
            color: #808080;
            text-align: right;
            padding: 15px 8px;
            border-right: 1px solid #ddd;
            user-select: none;
            font-family: var(--monospace-font);
            font-size: 14px;
            line-height: 1.5;
            overflow: hidden;
            min-width: 40px;
            white-space: pre;
            flex-shrink: 0;
            overflow-y: hidden;
        }
        
        /* 核心修复：确保所有元素使用正确的盒模型 */
        * {
            box-sizing: border-box !important;
            max-width: 100% !important;
        }
        
        /* 转换区域 - 固定尺寸 */
        .conversion-container {
            display: grid !important;
            grid-template-columns: 1fr 1fr !important;
            gap: 20px !important;
            align-items: start !important;
            width: 100% !important;
            overflow: hidden !important;
        }
        
        /* 输入输出面板容器 - 固定尺寸 */
        .io-panel-container {
            display: flex !important;
            flex-direction: column !important;
            width: 100% !important;
            overflow: hidden !important;
            flex-shrink: 0 !important;
        }
        
        /* 面板头部 */
        .panel-header {
            flex-shrink: 0 !important;
            margin-bottom: 10px !important;
        }
        
        /* 文本区域包装器 - 核心固定尺寸 */
        .textarea-wrapper {
            height: 400px !important;
            overflow: hidden !important;
            position: relative !important;
            width: 100% !important;
            display: block !important;
            flex-shrink: 0 !important;
        }
        
        /* 文本区域容器 - 固定尺寸 */
        .textarea-container {
            position: absolute !important;
            top: 0 !important;
            left: 0 !important;
            width: 100% !important;
            height: 100% !important;
            overflow: hidden !important;
            z-index: 10 !important;
        }
        
        /* 带行号的高亮区域 - 固定尺寸 */
        .lined-area {
            height: 100% !important;
            display: flex !important;
            z-index: 5 !important;
            overflow: hidden !important;
            width: 100% !important;
        }
        
        /* 确保输出区域的高度固定，不被内容拉伸 */
        #outputHighlightedArea {
            height: 100% !important;
            overflow: hidden !important;
        }
        
        /* 确保内容区域只在垂直方向滚动 */
        .content-area {
            overflow-y: auto !important;
            overflow-x: auto !important;
            min-height: 0 !important;
        }
        
        /* 行号区域 */
        .line-numbers {
            flex-shrink: 0 !important;
            width: 40px !important;
        }
        
        /* 内容区域 - 核心滚动样式 */
        .content-area {
            flex: 1 !important;
            padding: 15px !important;
            overflow: auto !important;
            font-family: var(--monospace-font) !important;
            font-size: 14px !important;
            line-height: 1.5 !important;
            background-color: #fafafa !important;
            white-space: pre-wrap !important;
            word-wrap: break-word !important;
            word-break: break-all !important;
            width: calc(100% - 60px) !important;
            min-width: 0 !important;
        }
        
        /* 高亮内容 - 确保不会拉伸容器 */
        .highlighted-content {
            margin: 0 !important;
            white-space: pre-wrap !important;
            word-wrap: break-word !important;
            word-break: break-all !important;
            overflow: visible !important;
        }
        
        /* 所有文本区域 - 固定尺寸 */
        textarea {
            width: 100% !important;
            height: 100% !important;
            padding: 15px 15px 15px 58px !important;
            border: 1px solid var(--border-color) !important;
            border-radius: var(--border-radius) !important;
            font-family: var(--monospace-font) !important;
            font-size: 14px !important;
            line-height: 1.5 !important;
            overflow: auto !important;
            white-space: pre-wrap !important;
            resize: none !important;
            box-sizing: border-box !important;
            word-wrap: break-word !important;
            word-break: break-all !important;
        }
        
        /* 按钮组 */
        .action-buttons {
            flex-shrink: 0 !important;
            margin-top: 10px !important;
        }
        
        /* 底部占位符 */
        .io-panel-container > div:last-child {
            flex-shrink: 0 !important;
        }
        
        /* 确保输入框可以接收焦点 */
        textarea:focus {
            outline: none !important;
            border-color: var(--primary-color) !important;
            box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.1) !important;
            z-index: 15 !important;
        }
        
        /* 确保输入区域可以正常接收输入 */
        #xmlInput, #jsonInput {
            position: relative !important;
            z-index: 20 !important;
            pointer-events: auto !important;
            user-select: text !important;
        }
        
        /* 输出区域特殊处理 - 确保不会被拉长 */
        #output, #outputTextAreaContainer, #outputHighlightedArea {
            max-width: 100% !important;
            overflow: auto !important;
            width: 100% !important;
            height: 100% !important;
        }
        
        /* 确保所有子元素不会拉伸父容器 */
        .conversion-container > * {
            overflow: hidden !important;
            max-width: 100% !important;
        }
        
        /* 确保整个工具卡片不会被拉伸 */
        .tool-card {
            overflow: hidden !important;
            max-width: 100% !important;
        }
        
        textarea {
            width: 100%;
            height: 100%;
            padding: 15px 15px 15px 58px;
            border: 1px solid var(--border-color);
            border-radius: var(--border-radius);
            font-family: var(--monospace-font);
            font-size: 14px;
            resize: vertical;
            line-height: 1.5;
            overflow: auto;
            box-sizing: border-box;
        }
        
        textarea:focus {
            outline: none;
            border-color: var(--primary-color);
            box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.1);
        }
        
        /* 交换按钮样式 */
        .swap-container {
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 10px;
        }
        
        .swap-btn {
            width: 50px;
            height: 50px;
            border-radius: 50%;
            font-size: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 0;
            cursor: pointer;
            transition: all 0.3s ease;
        }
        
        .swap-btn:hover {
            transform: scale(1.1);
        }
        
        /* 底部操作按钮样式 */
        .action-buttons {
            display: flex;
            justify-content: center;
            gap: 10px;
            margin-top: 20px;
        }
        
        /* 转换容器样式 */
        .conversion-container {
            margin-bottom: 15px;
        }
        
        /* 中间操作区域样式 */
        .middle-actions {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            gap: 10px;
            padding: 15px 10px;
            background-color: var(--background-color);
            border-radius: var(--border-radius);
            min-height: 200px;
        }
        
        /* 交换按钮样式 */
        .swap-btn {
            background-color: var(--primary-color);
            color: white;
            border: none;
            width: 60px;
            height: 60px;
            border-radius: 50%;
            font-size: 24px;
            cursor: pointer;
            transition: all 0.3s ease;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .swap-btn:hover {
            background-color: var(--primary-hover);
            transform: scale(1.1);
        }
        
        /* 辅助功能按钮组样式 */
        .helper-btn-group {
            display: flex;
            justify-content: center;
            gap: 10px;
            margin-top: 20px;
            flex-wrap: wrap;
        }
        
        /* 输入输出区域底部样式 */
        .io-footer {
            margin-top: 10px;
            text-align: right;
        }
        
        /* XML语法高亮样式 */
        .xml-tag {
            color: #0000ff;
        }
        
        .xml-attribute {
            color: #a31515;
        }
        
        .xml-value {
            color: #006400;
        }
        
        .xml-comment {
            color: #808080;
            font-style: italic;
        }
        
        .xml-processor {
            color: #808080;
        }
        
        /* JSON语法高亮样式 */
        .json-key {
            color: #a31515;
        }
        
        .json-string {
            color: #006400;
        }
        
        .json-number {
            color: #098658;
        }
        
        .json-boolean {
            color: #0000ff;
        }
        
        .json-null {
            color: #808080;
        }
        
        /* 提示信息 */
        .tip {
            background-color: #e8f4f8;
            color: #2980b9;
            padding: 10px 15px;
            border-radius: var(--border-radius);
            font-size: 13px;
            margin-top: 15px;
        }
        
        /* 响应式设计 */
        @media (max-width: 768px) {
            .io-container {
                flex-direction: column;
            }
            
            .btn-group {
                flex-direction: column;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>XML/JSON互转工具</h1>
            <a href="index.html" class="back-btn">返回主页</a>
        </header>
        
        <div class="tool-card">
            <!-- 转换区域 -->
            <div class="conversion-container" style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start;">
                <!-- 左侧输入区域 -->
                <div class="io-panel-container">
                    <div class="panel-header" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
                        <h3 style="margin: 0; color: #2c3e50; font-size: 18px;">输入</h3>
                        <div class="input-tabs" style="display: flex;">
                            <button class="btn btn-secondary" onclick="switchToXmlInput()" id="xmlTab" style="border-radius: 5px 0 0 5px; font-size: 13px; padding: 6px 12px;">XML</button>
                            <button class="btn btn-secondary" onclick="switchToJsonInput()" id="jsonTab" style="border-radius: 0 5px 5px 0; font-size: 13px; padding: 6px 12px;">JSON</button>
                        </div>
                    </div>
                    <!-- XML输入区域 -->
                    <div id="xmlInputSection">
                        <div class="textarea-wrapper" style="height: 400px;">
                            <!-- 文本区域容器 -->
                            <div id="xmlTextAreaContainer" class="textarea-container">
                                <textarea id="xmlInput" placeholder="请输入XML内容..." style="height: 100%;"></textarea>
                            </div>
                            <!-- 带行号的高亮区域 -->
                            <div id="xmlHighlightedArea" class="lined-area" style="display: none; height: 100%;">
                                <div id="xmlLineNumbers" class="line-numbers"></div>
                                <div id="xmlContentArea" class="content-area">
                                    <pre id="xmlHighlightedContent" class="highlighted-content"></pre>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!-- JSON输入区域 -->
                    <div id="jsonInputSection" style="display: none;">
                        <div class="textarea-wrapper" style="height: 400px;">
                            <!-- 文本区域容器 -->
                            <div id="jsonTextAreaContainer" class="textarea-container">
                                <textarea id="jsonInput" placeholder="请输入JSON内容..." style="height: 100%;"></textarea>
                            </div>
                            <!-- 带行号的高亮区域 -->
                            <div id="jsonHighlightedArea" class="lined-area" style="display: none; height: 100%;">
                                <div id="jsonLineNumbers" class="line-numbers"></div>
                                <div id="jsonContentArea" class="content-area">
                                    <pre id="jsonHighlightedContent" class="highlighted-content"></pre>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!-- 左侧底部操作按钮 -->
                    <div class="action-buttons" style="display: flex; justify-content: center; gap: 15px; margin-top: 10px;">
                        <button class="btn" onclick="convert()">转换</button>
                        <button class="btn btn-secondary" onclick="clearInput()">清空</button>
                    </div>
                </div>
                
                <!-- 右侧输出区域 -->
                <div class="io-panel-container">
                    <div class="panel-header" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
                        <h3 style="margin: 0; color: #2c3e50; font-size: 18px;">输出</h3>
                        <div style="display: flex; gap: 5px;">
                            <span id="outputType" style="margin-right: 10px; font-weight: bold;">JSON</span>：
                            <div style="display: flex; gap: 5px;">
                                <button class="btn btn-secondary" style="padding: 6px 12px; font-size: 13px;" onclick="swapInputs()">交换</button>
                                <button class="btn btn-secondary" style="padding: 6px 12px; font-size: 13px;" onclick="copyOutput()">复制</button>
                            </div>
                        </div>
                    </div>
                    <div class="textarea-wrapper" style="height: 400px;">
                        <div id="outputTextAreaContainer" class="textarea-container">
                            <textarea id="output" placeholder="转换结果将显示在这里..." readonly style="height: 100%;"></textarea>
                        </div>
                        <!-- 带行号的高亮区域 -->
                        <div id="outputHighlightedArea" class="lined-area" style="display: none; height: 100%;">
                            <div id="outputLineNumbers" class="line-numbers"></div>
                            <div id="outputContentArea" class="content-area">
                                <pre id="outputHighlightedContent" class="highlighted-content"></pre>
                            </div>
                        </div>
                    </div>
                    <!-- 右侧底部占位符，与左侧操作按钮区域对齐 -->
                    <div style="height: 40px; margin-top: 10px;"></div>
                </div>
            </div>
            
            <!-- 响应式布局：在小屏幕上显示为上下布局 -->
            <style>
                @media (max-width: 1024px) {
                    .conversion-container {
                        grid-template-columns: 1fr !important;
                    }
                    
                    .textarea-wrapper {
                        height: 300px !important;
                    }
                }
                
                /* 确保两个面板容器高度一致 */
                .io-panel-container {
                    display: flex;
                    flex-direction: column;
                }
                
                /* 确保所有textarea-wrapper高度一致 */
                .textarea-wrapper {
                    height: 400px !important;
                    flex-shrink: 0 !important;
                    min-height: 400px !important;
                }
            </style>
            
            <!-- 辅助功能按钮组 -->
            <div class="helper-btn-group" style="margin-top: 20px; display: flex; justify-content: center; gap: 10px; flex-wrap: wrap;">
                <button class="btn btn-secondary" onclick="loadExampleXml()">加载示例XML</button>
                <button class="btn btn-secondary" onclick="loadExampleJson()">加载示例JSON</button>
            </div>
            
            <!-- 提示信息 -->
            <div class="tip" style="margin-top: 20px;">
                支持标准XML和JSON格式的相互转换。转换后的结果会自动填充到对应的输入框中。
            </div>
        </div>
    </div>
    
    <script>
        // 生成行号
        function generateLineNumbers(content) {
            const lines = content.split('\n');
            let lineNumbers = '';
            for (let i = 1; i <= lines.length; i++) {
                lineNumbers += i + '\n';
            }
            return lineNumbers;
        }
        
        // XML语法高亮函数
        function highlightXML(xml) {
            if (!xml) return '';
            
            // 创建临时元素用于安全转义
            const tempDiv = document.createElement('div');
            tempDiv.textContent = xml;
            const escapedXml = tempDiv.innerHTML;
            
            // 高亮注释
            let highlighted = escapedXml.replace(/(&lt;!--[\s\S]*?--&gt;)/g, '<span class="xml-comment">$1</span>');
            
            // 高亮处理指令
            highlighted = highlighted.replace(/(&lt;\?[\s\S]*?\?&gt;)/g, '<span class="xml-processor">$1</span>');
            
            // 高亮CDATA
            highlighted = highlighted.replace(/(&lt;!\[CDATA\[[\s\S]*?\]\]&gt;)/g, '<span class="xml-processor">$1</span>');
            
            // 高亮标签
            highlighted = highlighted.replace(/(&lt;\/?)([a-zA-Z0-9_:-]+)(?=[^>]*&gt;)/g, '$1<span class="xml-tag">$2</span>');
            
            // 高亮属性
            highlighted = highlighted.replace(/([a-zA-Z0-9_:-]+)(=)(?=[^>]*&gt;)/g, '<span class="xml-attribute">$1</span>$2');
            
            // 高亮属性值
            highlighted = highlighted.replace(/(=)(&quot;.*?&quot;|&#39;.*?&#39;)(?=[^>]*&gt;)/g, '$1<span class="xml-value">$2</span>');
            
            return highlighted;
        }
        
        // JSON语法高亮函数
        function highlightJSON(json) {
            if (!json) return '';
            
            // 创建临时元素用于安全转义
            const tempDiv = document.createElement('div');
            tempDiv.textContent = json;
            const escapedJson = tempDiv.innerHTML;
            
            // 高亮JSON语法
            let highlighted = escapedJson
                // 高亮键名
                .replace(/"([a-zA-Z0-9_]+)":/g, '<span class="json-key">"$1"</span>:')
                // 高亮字符串值
                .replace(/:"(.*?)"/g, ': <span class="json-string">"$1"</span>')
                // 高亮数字
                .replace(/:(\s*)([0-9]+\.?[0-9]*)/g, ':$1<span class="json-number">$2</span>')
                // 高亮布尔值
                .replace(/:(\s*)(true|false)/g, ':$1<span class="json-boolean">$2</span>')
                // 高亮null值
                .replace(/:(\s*)(null)/g, ':$1<span class="json-null">$2</span>');
            
            return highlighted;
        }
        
        // 当前输入类型：'xml' 或 'json'
        let currentInputType = 'xml';
        
        // 清空输出框
        function clearOutput() {
            // 清空输出textarea
            document.getElementById('output').value = '';
            
            // 显示textarea，隐藏高亮结果
            document.getElementById('outputTextAreaContainer').style.display = 'block';
            document.getElementById('outputHighlightedArea').style.display = 'none';
        }
        
        // 切换到XML输入
        function switchToXmlInput() {
            currentInputType = 'xml';
            document.getElementById('xmlInputSection').style.display = 'block';
            document.getElementById('jsonInputSection').style.display = 'none';
            document.getElementById('xmlTab').className = 'btn';
            document.getElementById('jsonTab').className = 'btn btn-secondary';
            document.getElementById('outputType').textContent = 'JSON';
            
            // 切换输入格式时清空输出框
            clearOutput();
        }
        
        // 切换到JSON输入
        function switchToJsonInput() {
            currentInputType = 'json';
            document.getElementById('xmlInputSection').style.display = 'none';
            document.getElementById('jsonInputSection').style.display = 'block';
            document.getElementById('xmlTab').className = 'btn btn-secondary';
            document.getElementById('jsonTab').className = 'btn';
            document.getElementById('outputType').textContent = 'XML';
            
            // 切换输入格式时清空输出框
            clearOutput();
        }
        
        // 简化的XML格式化函数
        function formatXml(xml) {
            if (!xml) return '';
            
            let formatted = '';
            let indent = 0;
            let inTag = false;
            let tagStart = 0;
            
            for (let i = 0; i < xml.length; i++) {
                const char = xml[i];
                
                if (char === '<') {
                    // 处理标签开始
                    inTag = true;
                    tagStart = i;
                    
                    // 在标签开始前添加换行和缩进
                    if (i > 0 && xml[i-1] !== '<') {
                        formatted += '\n' + '  '.repeat(indent);
                    }
                } else if (char === '>') {
                    // 处理标签结束
                    inTag = false;
                    const tag = xml.substring(tagStart, i + 1);
                    
                    // 添加标签
                    formatted += tag;
                    
                    // 检查标签类型
                    if (tag.startsWith('</')) {
                        // 结束标签，减少缩进
                        indent--;
                    } else if (!tag.startsWith('<?') && !tag.startsWith('<!') && !tag.endsWith('/>')) {
                        // 开始标签，增加缩进
                        indent++;
                    }
                } else if (!inTag) {
                    // 文本内容，直接添加
                    formatted += char;
                }
            }
            
            // 清理多余的空格和换行
            formatted = formatted.replace(/\s+/g, ' ')
                                .replace(/\s*<\s*/g, '<')
                                .replace(/\s*>\s*/g, '>')
                                .replace(/<\s*/g, '<')
                                .replace(/\s*>/g, '>');
            
            // 重新添加换行和缩进
            let finalFormatted = '';
            indent = 0;
            inTag = false;
            tagStart = 0;
            
            for (let i = 0; i < formatted.length; i++) {
                const char = formatted[i];
                
                if (char === '<') {
                    inTag = true;
                    tagStart = i;
                    
                    if (i > 0) {
                        finalFormatted += '\n' + '  '.repeat(indent);
                    }
                } else if (char === '>') {
                    inTag = false;
                    const tag = formatted.substring(tagStart, i + 1);
                    finalFormatted += tag;
                    
                    if (tag.startsWith('</')) {
                        indent--;
                    } else if (!tag.startsWith('<?') && !tag.startsWith('<!') && !tag.endsWith('/>')) {
                        indent++;
                    }
                } else if (!inTag) {
                    finalFormatted += char;
                }
            }
            
            return finalFormatted.trim();
        }
        
        // 简单可靠的XML格式化函数
        function formatXmlSimple(xml) {
            if (!xml) return '';
            
            let formatted = '';
            let indent = 0;
            let inTag = false;
            let tagContent = '';
            
            for (let i = 0; i < xml.length; i++) {
                const char = xml[i];
                
                if (char === '<') {
                    inTag = true;
                    tagContent = '<';
                    
                    // 在标签开始前添加换行和缩进
                    if (i > 0 && xml[i-1] === '>') {
                        formatted += '\n' + '  '.repeat(indent);
                    }
                } else if (char === '>') {
                    tagContent += '>';
                    inTag = false;
                    
                    formatted += tagContent;
                    
                    // 更新缩进
                    if (tagContent.startsWith('</')) {
                        indent--;
                    } else if (!tagContent.startsWith('<?') && !tagContent.startsWith('<!') && !tagContent.endsWith('/>')) {
                        indent++;
                    }
                } else if (inTag) {
                    tagContent += char;
                } else {
                    formatted += char;
                }
            }
            
            return formatted.trim();
        }
        
        // 统一转换函数
        function convert() {
            try {
                if (currentInputType === 'xml') {
                    // XML转JSON
                    const xmlInput = document.getElementById('xmlInput').value.trim();
                    if (!xmlInput) {
                        alert('请输入XML内容');
                        return;
                    }
                    
                    // 检查XML是否有根元素
                    if (!xmlInput.match(/^\s*<[^>]+>/) || !xmlInput.match(/<\/[^>]+>\s*$/)) {
                        throw new Error('XML必须包含有效的根元素');
                    }
                    
                    const parser = new DOMParser();
                    const xmlDoc = parser.parseFromString(xmlInput, 'text/xml');
                    
                    // 检查XML是否有效
                    const parserError = xmlDoc.getElementsByTagName('parsererror');
                    if (parserError.length > 0) {
                        throw new Error('XML格式无效：' + parserError[0].textContent);
                    }
                    
                    // 获取根元素名称
                    const rootElement = xmlDoc.documentElement;
                    const rootName = rootElement.nodeName;
                    
                    // 转换整个XML文档，保留最外层字段
                    const jsonObj = {};
                    jsonObj[rootName] = xmlToJsonRecursive(rootElement);
                    
                    const jsonString = JSON.stringify(jsonObj, null, 2);
                    updateOutput(jsonString, 'json');
                } else {
                    // JSON转XML
                    const jsonInput = document.getElementById('jsonInput').value.trim();
                    if (!jsonInput) {
                        alert('请输入JSON内容');
                        return;
                    }
                    
                    const jsonObj = JSON.parse(jsonInput);
                    let xmlString = '';
                    
                    // 直接生成XML
                    if (typeof jsonObj === 'object' && jsonObj !== null && Object.keys(jsonObj).length === 1) {
                        // 如果JSON只有一个顶级键，用它作为根元素名称
                        const rootName = Object.keys(jsonObj)[0];
                        xmlString = generateXmlFromObject(jsonObj[rootName], rootName);
                    } else {
                        // 否则使用默认根元素
                        xmlString = generateXmlFromObject(jsonObj, 'root');
                    }
                    
                    // 使用简单可靠的格式化函数
                    const formattedXml = formatXmlSimple(xmlString);
                    updateOutput(formattedXml, 'xml');
                }
            } catch (err) {
                console.error('转换错误:', err);
                alert('转换失败：' + err.message);
            }
        }
        
        // 非递归方式生成XML
        function generateXmlFromObject(obj, rootName) {
            let xml = `<${rootName}`;
            
            // 处理属性
            if (obj['@attributes']) {
                for (const [attrName, attrValue] of Object.entries(obj['@attributes'])) {
                    xml += ` ${attrName}="${attrValue}"`;
                }
            }
            
            xml += '>';
            
            // 处理文本内容
            if (obj['#text'] !== undefined) {
                xml += obj['#text'];
            } else if (Array.isArray(obj)) {
                // 处理数组
                for (const item of obj) {
                    xml += generateXmlFromObject(item, rootName);
                }
            } else if (typeof obj === 'object' && obj !== null) {
                // 处理对象的子属性
                for (const [key, value] of Object.entries(obj)) {
                    // 跳过特殊属性
                    if (key === '@attributes' || key === '#text') {
                        continue;
                    }
                    
                    if (Array.isArray(value)) {
                        // 处理数组属性
                        for (const item of value) {
                            xml += generateXmlFromObject(item, key);
                        }
                    } else if (typeof value === 'object' && value !== null) {
                        // 处理对象属性
                        xml += generateXmlFromObject(value, key);
                    } else {
                        // 处理基本类型属性
                        xml += `<${key}>${value}</${key}>`;
                    }
                }
            } else {
                // 处理基本类型
                xml += obj;
            }
            
            xml += `</${rootName}>`;
            return xml;
        }
        
        // 修复的XML格式化函数
        function formatXmlSimple(xml) {
            if (!xml) return '';
            
            let formatted = '';
            let indent = 0;
            let inTag = false;
            let tagContent = '';
            let isEndTag = false;
            let isSelfClosing = false;
            
            for (let i = 0; i < xml.length; i++) {
                const char = xml[i];
                
                if (char === '<') {
                    inTag = true;
                    tagContent = '<';
                    isEndTag = false;
                    isSelfClosing = false;
                    
                    // 在标签开始前添加换行和缩进
                    if (i > 0 && xml[i-1] === '>') {
                        formatted += '\n' + '  '.repeat(indent);
                    }
                } else if (char === '>') {
                    tagContent += '>';
                    inTag = false;
                    
                    // 检查标签类型
                    isEndTag = tagContent.startsWith('</');
                    isSelfClosing = tagContent.endsWith('/>');
                    
                    // 更新缩进
                    if (isEndTag) {
                        indent--;
                    }
                    
                    // 添加标签
                    formatted += tagContent;
                    
                    // 更新缩进（开始标签）
                    if (!isEndTag && !tagContent.startsWith('<?') && !tagContent.startsWith('<!') && !isSelfClosing) {
                        indent++;
                    }
                } else if (inTag) {
                    tagContent += char;
                } else {
                    formatted += char;
                }
            }
            
            return formatted.trim();
        }
        
        // 更新输出函数
        function updateOutput(content, type) {
            const output = document.getElementById('output');
            const outputTextAreaContainer = document.getElementById('outputTextAreaContainer');
            const outputHighlightedArea = document.getElementById('outputHighlightedArea');
            const outputLineNumbers = document.getElementById('outputLineNumbers');
            const outputHighlightedContent = document.getElementById('outputHighlightedContent');
            const outputContentArea = document.getElementById('outputContentArea');
            
            // 确保内容是字符串类型
            const contentStr = typeof content === 'string' ? content : String(content);
            
            // 更新textarea的值
            output.value = contentStr;
            
            if (contentStr.trim()) {
                // 显示高亮结果，隐藏textarea
                const highlighted = type === 'xml' ? highlightXML(contentStr) : highlightJSON(contentStr);
                
                // 生成行号
                outputLineNumbers.textContent = generateLineNumbers(contentStr);
                
                // 更新高亮内容
                outputHighlightedContent.innerHTML = highlighted;
                
                // 显示高亮区域，隐藏textarea
                outputTextAreaContainer.style.display = 'none';
                outputHighlightedArea.style.display = 'flex';
                
                // 移除之前的滚动事件监听器，避免重复添加
                const oldScrollHandler = outputContentArea.__scrollHandler;
                if (oldScrollHandler) {
                    outputContentArea.removeEventListener('scroll', oldScrollHandler);
                }
                
                // 添加新的滚动事件监听器，确保行号与内容同步滚动
                const newScrollHandler = function() {
                    outputLineNumbers.scrollTop = outputContentArea.scrollTop;
                };
                outputContentArea.__scrollHandler = newScrollHandler;
                outputContentArea.addEventListener('scroll', newScrollHandler);
            } else {
                // 显示textarea，隐藏高亮结果
                outputTextAreaContainer.style.display = 'block';
                outputHighlightedArea.style.display = 'none';
            }
        }
        
        // 清空输入
        function clearInput() {
            if (currentInputType === 'xml') {
                document.getElementById('xmlInput').value = '';
                updateXmlDisplay('');
            } else {
                document.getElementById('jsonInput').value = '';
                updateJsonDisplay('');
            }
            // 清空输出
            document.getElementById('output').value = '';
            document.getElementById('outputTextAreaContainer').style.display = 'block';
            document.getElementById('outputHighlightedArea').style.display = 'none';
        }
        
        // 更新XML输入显示
        function updateXmlDisplay(content) {
            const xmlTextAreaContainer = document.getElementById('xmlTextAreaContainer');
            const xmlHighlightedArea = document.getElementById('xmlHighlightedArea');
            const xmlLineNumbers = document.getElementById('xmlLineNumbers');
            const xmlHighlightedContent = document.getElementById('xmlHighlightedContent');
            const xmlContentArea = document.getElementById('xmlContentArea');
            
            // 确保内容是字符串类型
            const contentStr = typeof content === 'string' ? content : String(content);
            
            if (contentStr.trim()) {
                // 显示高亮结果，隐藏textarea
                const highlighted = highlightXML(contentStr);
                
                // 生成行号
                xmlLineNumbers.textContent = generateLineNumbers(contentStr);
                
                // 更新高亮内容
                xmlHighlightedContent.innerHTML = highlighted;
                
                // 显示高亮区域，隐藏textarea
                xmlTextAreaContainer.style.display = 'none';
                xmlHighlightedArea.style.display = 'flex';
                
                // 移除之前的滚动事件监听器，避免重复添加
                const oldScrollHandler = xmlContentArea.__scrollHandler;
                if (oldScrollHandler) {
                    xmlContentArea.removeEventListener('scroll', oldScrollHandler);
                }
                
                // 添加新的滚动事件监听器，确保行号与内容同步滚动
                const newScrollHandler = function() {
                    xmlLineNumbers.scrollTop = xmlContentArea.scrollTop;
                };
                xmlContentArea.__scrollHandler = newScrollHandler;
                xmlContentArea.addEventListener('scroll', newScrollHandler);
            } else {
                // 显示textarea，隐藏高亮结果
                xmlTextAreaContainer.style.display = 'block';
                xmlHighlightedArea.style.display = 'none';
            }
        }
        
        // 更新JSON输入显示
        function updateJsonDisplay(content) {
            const jsonTextAreaContainer = document.getElementById('jsonTextAreaContainer');
            const jsonHighlightedArea = document.getElementById('jsonHighlightedArea');
            const jsonLineNumbers = document.getElementById('jsonLineNumbers');
            const jsonHighlightedContent = document.getElementById('jsonHighlightedContent');
            const jsonContentArea = document.getElementById('jsonContentArea');
            
            // 确保内容是字符串类型
            const contentStr = typeof content === 'string' ? content : String(content);
            
            if (contentStr.trim()) {
                // 显示高亮结果，隐藏textarea
                const highlighted = highlightJSON(contentStr);
                
                // 生成行号
                jsonLineNumbers.textContent = generateLineNumbers(contentStr);
                
                // 更新高亮内容
                jsonHighlightedContent.innerHTML = highlighted;
                
                // 显示高亮区域，隐藏textarea
                jsonTextAreaContainer.style.display = 'none';
                jsonHighlightedArea.style.display = 'flex';
                
                // 移除之前的滚动事件监听器，避免重复添加
                const oldScrollHandler = jsonContentArea.__scrollHandler;
                if (oldScrollHandler) {
                    jsonContentArea.removeEventListener('scroll', oldScrollHandler);
                }
                
                // 添加新的滚动事件监听器，确保行号与内容同步滚动
                const newScrollHandler = function() {
                    jsonLineNumbers.scrollTop = jsonContentArea.scrollTop;
                };
                jsonContentArea.__scrollHandler = newScrollHandler;
                jsonContentArea.addEventListener('scroll', newScrollHandler);
            } else {
                // 显示textarea，隐藏高亮结果
                jsonTextAreaContainer.style.display = 'block';
                jsonHighlightedArea.style.display = 'none';
            }
        }
        
        // 递归将XML转换为JSON
        function xmlToJsonRecursive(node) {
            // 处理属性
            const attributes = {};
            if (node.attributes.length > 0) {
                for (let i = 0; i < node.attributes.length; i++) {
                    const attr = node.attributes[i];
                    attributes[attr.nodeName] = attr.nodeValue;
                }
            }
            
            // 处理子节点
            let textContent = '';
            const elementChildren = {};
            let hasElementChildren = false;
            
            // 收集文本内容和元素子节点
            if (node.hasChildNodes()) {
                for (let i = 0; i < node.childNodes.length; i++) {
                    const child = node.childNodes[i];
                    if (child.nodeType === 3) {
                        // 文本节点，只保留非空白内容
                        const trimmedText = child.nodeValue.trim();
                        if (trimmedText) {
                            textContent += trimmedText;
                        }
                    } else if (child.nodeType === 1) {
                        // 元素节点
                        hasElementChildren = true;
                        const childName = child.nodeName;
                        const childResult = xmlToJsonRecursive(child);
                        
                        if (elementChildren[childName] === undefined) {
                            elementChildren[childName] = childResult;
                        } else {
                            if (!Array.isArray(elementChildren[childName])) {
                                elementChildren[childName] = [elementChildren[childName]];
                            }
                            elementChildren[childName].push(childResult);
                        }
                    }
                }
            }
            
            // 构建最终结果
            if (!hasElementChildren) {
                // 只有文本内容，没有元素子节点
                if (Object.keys(attributes).length === 0) {
                    // 没有属性，直接返回文本内容
                    return textContent;
                } else {
                    // 有属性，返回带属性和文本的对象
                    const result = { ...attributes };
                    result['#text'] = textContent;
                    return result;
                }
            } else {
                // 有元素子节点
                const result = { ...elementChildren };
                
                // 如果有属性，添加到结果中
                if (Object.keys(attributes).length > 0) {
                    result['@attributes'] = attributes;
                }
                
                // 如果还有文本内容（通常是混合内容），添加到结果中
                if (textContent) {
                    result['#text'] = textContent;
                }
                
                return result;
            }
        }
        
        // 格式化XML
        function formatXml(xml) {
            if (!xml) return '';
            
            // 首先压缩XML，去除多余的空格和换行
            const compressed = xml
                .replace(/\s+/g, ' ') // 替换所有空白字符为单个空格
                .replace(/\s*<\s*/g, '<') // 移除标签前的空格
                .replace(/\s*>\s*/g, '>') // 移除标签后的空格
                .trim();
            
            let formatted = '';
            let indent = 0;
            let currentDepth = 0;
            let i = 0;
            
            while (i < compressed.length) {
                let char = compressed[i];
                
                if (char === '<') {
                    // 找到标签结束位置
                    let endIndex = compressed.indexOf('>', i);
                    if (endIndex === -1) {
                        break;
                    }
                    
                    let tag = compressed.substring(i, endIndex + 1);
                    let isEndTag = tag.startsWith('</');
                    let isStartTag = !isEndTag && !tag.startsWith('<?') && !tag.startsWith('<!') && !tag.endsWith('/>');
                    let isSelfClosing = tag.endsWith('/>');
                    
                    // 如果是结束标签，先减少缩进
                    if (isEndTag) {
                        currentDepth--;
                    }
                    
                    // 添加换行和缩进
                    if (i > 0 && compressed[i-1] === '>') {
                        formatted += '\n' + '  '.repeat(currentDepth);
                    }
                    
                    // 添加标签
                    formatted += tag;
                    
                    // 如果是开始标签，增加缩进
                    if (isStartTag) {
                        currentDepth++;
                    }
                    
                    // 检查标签内部是否有文本内容
                    if (isStartTag && !isSelfClosing) {
                        let nextTagStart = compressed.indexOf('<', endIndex + 1);
                        // 如果下一个字符不是标签，说明有文本内容
                        if (nextTagStart !== endIndex + 1) {
                            // 提取文本内容
                            let text = compressed.substring(endIndex + 1, nextTagStart).trim();
                            if (text) {
                                // 直接添加文本内容，不换行
                                formatted += text;
                                // 跳过文本内容
                                i = nextTagStart - 1;
                            }
                        }
                    }
                    
                    // 跳过整个标签
                    i = endIndex + 1;
                } else {
                    // 文本内容，直接添加
                    formatted += char;
                    i++;
                }
            }
            
            // 清理多余的换行和空格
            formatted = formatted
                .replace(/\n\s*\n/g, '\n')
                .replace(/^\s+/, '')
                .replace(/\s+$/, '');
            
            return formatted;
        }
        
        // 递归将JSON转换为XML
        function jsonToXmlRecursive(obj, rootName = 'root') {
            let xml = '';
            
            // 处理基本类型
            if (typeof obj !== 'object' || obj === null) {
                xml = `<${rootName}>${obj}</${rootName}>`;
                return xml;
            }
            
            // 处理数组
            if (Array.isArray(obj)) {
                for (const item of obj) {
                    xml += jsonToXmlRecursive(item, rootName);
                }
                return xml;
            }
            
            // 处理对象
            xml = `<${rootName}`;
            
            // 处理属性
            if (obj['@attributes']) {
                for (const [attrName, attrValue] of Object.entries(obj['@attributes'])) {
                    xml += ` ${attrName}="${attrValue}"`;
                }
            }
            
            xml += '>';
            
            // 处理文本内容
            if (obj['#text'] !== undefined) {
                xml += obj['#text'];
            } else {
                // 处理子节点
                for (const [childName, childValue] of Object.entries(obj)) {
                    // 跳过特殊键
                    if (childName === '@attributes' || childName === '#text') {
                        continue;
                    }
                    
                    // 递归处理子节点
                    xml += jsonToXmlRecursive(childValue, childName);
                }
            }
            
            xml += `</${rootName}>`;
            return xml;
        }
        
        // 复制输出
        function copyOutput() {
            const output = document.getElementById('output');
            output.select();
            
            try {
                if (navigator.clipboard && window.isSecureContext) {
                    navigator.clipboard.writeText(output.value).then(() => {
                        alert('输出内容已复制到剪贴板');
                    }).catch(err => {
                        document.execCommand('copy');
                        alert('输出内容已复制到剪贴板');
                    });
                } else {
                    document.execCommand('copy');
                    alert('输出内容已复制到剪贴板');
                }
            } catch (err) {
                alert('复制失败，请手动复制');
            }
        }
        
        // 交换输入输出
        function swapInputs() {
            const output = document.getElementById('output');
            if (!output.value.trim()) {
                alert('输出区域为空，无法交换');
                return;
            }
            
            if (currentInputType === 'xml') {
                // 当前是XML输入，JSON输出
                // 将JSON输出作为JSON输入，切换到JSON输入
                document.getElementById('jsonInput').value = output.value;
                updateJsonDisplay(output.value);
                switchToJsonInput();
            } else {
                // 当前是JSON输入，XML输出
                // 将XML输出作为XML输入，切换到XML输入
                document.getElementById('xmlInput').value = output.value;
                updateXmlDisplay(output.value);
                switchToXmlInput();
            }
            
            // 清空输出
            document.getElementById('output').value = '';
            document.getElementById('outputTextAreaContainer').style.display = 'block';
            document.getElementById('outputHighlightedArea').style.display = 'none';
        }
        
        // 加载示例XML
        function loadExampleXml() {
            const exampleXml = `<person>
    <name>John Doe</name>
    <age>30</age>
    <email>john@example.com</email>
    <address>
        <street>123 Main St</street>
        <city>New York</city>
        <country>USA</country>
    </address>
    <phone type="home">555-1234</phone>
    <phone type="work">555-5678</phone>
</person>`;
            document.getElementById('xmlInput').value = exampleXml;
            updateXmlDisplay(exampleXml);
            // 切换到XML输入
            switchToXmlInput();
        }
        
        // 加载示例JSON
        function loadExampleJson() {
            const exampleJson = `{
    "person": {
        "name": "John Doe",
        "age": 30,
        "email": "john@example.com",
        "address": {
            "street": "123 Main St",
            "city": "New York",
            "country": "USA"
        },
        "phone": [
            {
                "@attributes": {
                    "type": "home"
                },
                "#text": "555-1234"
            },
            {
                "@attributes": {
                    "type": "work"
                },
                "#text": "555-5678"
            }
        ]
    }
}`;
            document.getElementById('jsonInput').value = exampleJson;
            updateJsonDisplay(exampleJson);
            // 切换到JSON输入
            switchToJsonInput();
        }
        
        // 页面加载完成后初始化
        window.addEventListener('DOMContentLoaded', function() {
            // 初始化XML输入高亮
            updateXmlDisplay('');
            // 初始化JSON输入高亮
            updateJsonDisplay('');
        });
    </script>
</body>
</html>